﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Export.Ui.ViewModel
{
    using System.Collections.ObjectModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Windows.Threading;
    using DatabaseCore;
    using DatabaseCore.Dao;
    using GalaSoft.MvvmLight;
    using DatabaseCore.Dto;
    using System.Windows;
    using System.ComponentModel;
    using System.Windows.Input;
    using FirstFloor.ModernUI.Presentation;
    using SystemCore;
    using System.Transactions;

    public class QueueViewModel : ViewModelBase, INotifyPropertyChanged 
    {
        private ObservableCollection<ProdQueue> _queues = null;
        private ProdQueueDao queueProvider = new ProdQueueDao();
        private ProductQueueMappedDao productQueueMappedProvider = new ProductQueueMappedDao();
        private ProductSummaryDao summaryProvider = new ProductSummaryDao();
        private OrderDao orderProvider = new OrderDao();
        private OrderDetailDao orderDetailProvider = new OrderDetailDao();
        private ProdQueueDao proQueueProvider = new ProdQueueDao();

        private ProdQueue _selectedQueue;
        private int _selectedQueueIndex;
        

        public QueueViewModel(Dispatcher uidispatcher)
        {
            //InitialData(this, null);
            UIDispatcher = uidispatcher;
            Notifier = new SQLNotifier();
            Notifier.NewMessage += new EventHandler<SqlNotificationEventArgs>(notifier_NewMessage);
            DataTable dt = Notifier.RegisterDependency();

            //InitialData(dt);
            InitialCommand();
        }

        public Dispatcher UIDispatcher { get; set; }

        public SQLNotifier Notifier { get; set; }

        public ProdQueue SelectedQueue { 
            get
            {
                return _selectedQueue;
            }
            set
            {
                _selectedQueue = value;
            }
        }

        public int SelectedQueueIndex
        {
            get { return _selectedQueueIndex; }
            set {
                if (value != _selectedQueueIndex)
                {
                    _selectedQueueIndex = value;
                    OnPropertyChanged("SelectedQueueIndex");
                }
            }
        }

        public ObservableCollection<ProdQueue> Queues
        {
            get
            {
                _queues = _queues ?? new ObservableCollection<ProdQueue>();
                return _queues;
            }
        }

        public bool IsFirstRecord
        {
            get
            {
                return !(SelectedQueueIndex == 0);
            }
        }

        public bool IsLastRecord
        {
            get
            {
                return !(SelectedQueueIndex == _queues.Count - 1);
            }
        }

        public RelayCommand MoveQueueUpCommand { get; private set; }
        public RelayCommand MoveQueueDownCommand { get; private set; }
        public RelayCommand DisableQueueCommand { get; private set; }
        public RelayCommand EnableQueueCommand { get; private set; }
        public RelayCommand DeleteQueueCommand { get; private set; }
        public RelayCommand ChangePlantCommand { get; private set; }

        private void notifier_NewMessage(object sender, SqlNotificationEventArgs e)
        {
            var testdb = Notifier.RegisterDependency();
        }

        private void InitialData(DataTable dt)
        {
            this.UIDispatcher.BeginInvoke((Action)delegate()
            {
                if (dt != null)
                {
                    Queues.Clear();
                    foreach (DataRow q in dt.Rows)
                    {
                        ProdQueue queue = new ProdQueue
                        {
                            id = Convert.ToInt64((q["id"])),
                            ProductCode = q["ProductCode"].ToString(),
                            OrderNo = q["OrderNo"].ToString(),
                            Qty = Convert.ToDecimal(q["Qty"]),
                            PlantCode = (q["PlantCode"]).ToString(),
                            IsActive = Convert.ToBoolean(q["IsActive"]),
                            Rate = string.IsNullOrEmpty(q["Rate"].ToString()) ? new Int32?() : Convert.ToInt32(q["Rate"]),
                            ValidFrom = string.IsNullOrEmpty(q["ValidFrom"].ToString()) ? new DateTime?() : Convert.ToDateTime(q["ValidFrom"]),
                            ValidTo = string.IsNullOrEmpty(q["ValidTo"].ToString()) ? new DateTime?() : Convert.ToDateTime(q["ValidTo"]),
                            Date = Convert.ToDateTime(q["Date"] ?? DateTime.Today),
                            ProductName = q["ProductName"].ToString(),
                            RefOrderNo = q["RefOrderNo"].ToString(),
                            OriginalQty = Convert.ToInt32(q["OriginalQty"]),
                            Priority = Convert.ToInt32(q["Priority"])
                        };
                        Queues.Add(queue);
                    }
                }
            });
        }

        private void InitialCommand()
        {
            MoveQueueUpCommand = new RelayCommand(moveQueueUp);
            MoveQueueDownCommand = new RelayCommand(moveQueueDown);
            DisableQueueCommand = new RelayCommand(disableQueue);
            EnableQueueCommand = new RelayCommand(enableQueue);
            DeleteQueueCommand = new RelayCommand(deleteQueue);
            ChangePlantCommand = new RelayCommand(ChangePlant);
        }


        //TODO - Move Queue ไม่ควรจะมีดีกว่า? เพราะจะยุ่งยากเรื่องการจัด priority มาก
        //       เพราะมีการ sort queue ตาม materialno อยู่แล้ว
        //       ให้ไปใช้ enable, disable แทน
        //       ตอนนี้ยังมีไปก่อน
        #region MoveQueue

        private void moveQueueUp(object parameter)
        {
            moveQueue(parameter, true);
        }

        private void moveQueueDown(object parameter)
        {
            moveQueue(parameter, false);
        }

        private void moveQueue(object parameter, bool IsUp)
        {
            int queueIndex = -1;
            if (int.TryParse(parameter.ToString(), out queueIndex) && (int)parameter != -1)
            {
                if (IsUp)
                {
                    if (queueIndex != 0)
                    {
                        Queues.Move(queueIndex, queueIndex - 1);

                        AssignPriority();
                        queueProvider.UpdateQueuePriority(Queues.ToList());
                    }
                }
                else
                {
                    if (queueIndex < Queues.Count - 1)
                    {
                        Queues.Move(queueIndex, queueIndex + 1);

                        AssignPriority();
                        queueProvider.UpdateQueuePriority(Queues.ToList());
                    }
                }
            }
        }

        private void AssignPriority()
        {
            Parallel.ForEach(Queues, (x, pls, index) =>
            {
                x.Priority = (int)index + 1;
            });
        }

        #endregion

        #region DisableEnableQueue

        private void disableQueue(object parameter)
        {
            disableEnableQueue(parameter, true);
        }

        private void enableQueue(object parameter)
        {
            disableEnableQueue(parameter, false);
        }

        private void disableEnableQueue(object parameter, bool isDisable)
        {
            int queueIndex = -1;
            if (int.TryParse(parameter.ToString(), out queueIndex) && (int)parameter != -1)
            {
                if (isDisable)
                {
                    Queues[queueIndex].IsActive = false;
                }
                else
                {
                    Queues[queueIndex].IsActive = true;
                }

                proQueueProvider.UpdateQueuePause(Queues[queueIndex].id, Queues[queueIndex].IsActive);
            }
        }

        #endregion

        #region DeleteQueue

        private void deleteQueue(object parameter)
        {
            int queueIndex = -1;
            if (int.TryParse(parameter.ToString(), out queueIndex) && (int)parameter != -1)
            {
                using (var ts = new TransactionScope())
                {
                    //ลบใน ProdQueue
                    proQueueProvider.Delete(Queues[queueIndex].id);

                    var orderNo = Queues[queueIndex].OrderNo;
                    var materialNo = Queues[queueIndex].ProductCode;
                    var queueQty = Queues[queueIndex].Qty;
                    //ProductQueueMapped queueMapped = productQueueMappedProvider.GetByOrderNoAndMaterialNo(orderNo, materialNo);
                    //if (queueMapped != null)
                    //{
                    //    var mappedQty = queueMapped.Qty;


                    //TODO - ทำยังไงกับค่า ReceivedQty, RemainingQty ที่ OrderDetail (คิดว่าน่าจะเป็นเคสที่ 2)
                    // 1.ลบแล้ว OrderDetail นี้หายไปเลยไหม -> ลบใน QueueMapped -> เช็ค orderDetail ว่า Mapped หมดหรือยัง -> เปลี่ยน OrderStatus
                    // 2.เอาเท่าที่ Mapped ได้, หักค่าที่รอคิวอยู่ให้กับ OrderDetail (ลบจาก Remaining) -> เช็ค orderDetail ว่า Mapped หมดหรือยัง -> update OrderStatus

                    #region Case 2

                    //หักค่าที่รอคิวอยู่ให้กับ OrderDetail (ลบจาก Remaining)
                    orderDetailProvider.UpdateRemainingQtyByDeleteQueue(orderNo, materialNo, (int)queueQty, UserContext.FullName);

                    //เช็ค orderDetail ว่า Mapped หมดหรือยัง
                    bool isClosed = orderDetailProvider.IsOrderDetailCompleted(orderNo);
                    if (isClosed)
                    {
                        //update OrderStatus
                        orderProvider.UpdateOrderStatus(orderNo, (int)EOrderStatus.Closed, UserContext.FullName);
                    }

                    #endregion

                    ts.Complete();
                }
            }
        }

        #endregion

        #region Change Plant

        private void ChangePlant(object parameter)
        {
            int queueIndex = -1;
            if (int.TryParse(parameter.ToString(), out queueIndex) && (int)parameter != -1)
            {
                //TODO - TextChanged event should have oldValue & newValue
                var oldPlant = "2813";
                var newPlant = Queues[queueIndex].PlantCode;
                var qID = Queues[queueIndex].id;
                var orderNo = Queues[queueIndex].OrderNo;
                var materialNo = Queues[queueIndex].ProductCode;
                var originalQty = Queues[queueIndex].OriginalQty;

                using (var ts = new TransactionScope())
                {
                    //delete old plant in ProdQueue and QueueMapped
                    //proQueueProvider.Delete(qID);
                    productQueueMappedProvider.DeleteByOrderNoAndMaterialNoAndPlantCode(orderNo, materialNo, oldPlant);

                    //update receivedQty & remaining from QueueMapped to detail 
                    orderDetailProvider.UpdateRemainingQtyByChangePlant(orderNo, materialNo, UserContext.FullName);

                    //update plant & original qty to ProdQueue
                    //proQueueProvider.UpdateChangePlantAndQty(qID, newPlant, originalQty);

                    ts.Complete();

                    MessageBox.Show("Change plant success");
                }
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
}
